package fr.jhaccoun.demenager_eco.web.utilisateur;

import java.util.Locale;

import javax.validation.groups.Default;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.MessageSource;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;

import fr.jhaccoun.demenager_eco.commun.FriendlyException;
import fr.jhaccoun.demenager_eco.erreur.ValidateTechnicalErrorUtils;
import fr.jhaccoun.demenager_eco.utilisateur.UserCreationModificationPasswordValidatorGroup;
import fr.jhaccoun.demenager_eco.utilisateur.Utilisateur;
import fr.jhaccoun.demenager_eco.utilisateur.UtilisateurService;

//TODO Découper le controller User account controller en plusieus sous controller pour la visibilité et maintenance 

//TODO Harmonisation des noms de classe : Mettre User et non Utilisateur

@Controller
@RequestMapping(value = "/compte-utilisateur")
public class UserAccountController {

	private static final Logger LOGGER = LoggerFactory.getLogger(UserAccountController.class);
	
	@Autowired 
	private UtilisateurService userService;
	
	@Autowired
	private MessageSource messageSource;
	
	@Autowired
	private UserValidator userValidator;
	 
	@RequestMapping(value = "/creation", method = RequestMethod.GET)
	public String initCreatePage(Model model) { 
		LOGGER.info("Initialisation du compte utilisateur de creation");
		initModel(model,new UtilisateurForm());
		return getBuildedUrlPourCompteUtilisateur("creation-compte-utilisateur"); 
	}
	
	//TODO voir si interassant d'enrichir la méthode addUtilisateurServic avec un argument autoLogin boolean pour dire si lors de l'ajout il y a autoconnexion. Peut etre utile si inscription d'un user mais pas si inscription d'user via batch ou backoffice qui veut pas etre connecté avec l'user apres l'inscription

	@RequestMapping(value = "/creation", method = RequestMethod.POST)
	public String createUser(@ModelAttribute("compteForm") @Validated({Default.class,UserCreationModificationPasswordValidatorGroup.class}) UtilisateurForm compteForm, BindingResult bresult,RedirectAttributes redirectAttributes,Model model) { 
		LOGGER.info("Création du compte utilisateur de creation, compteForm:{}",compteForm);
		  
		userValidator.validate(compteForm, bresult);
		
		if (bresult.hasErrors()) {
			LOGGER.info("Erreur détecté lors de la validation du compte form"); 
			initModel(model,compteForm);
			LOGGER.info("Retour création compte avec erreurs"); 
			return getBuildedUrlPourCompteUtilisateur("creation-compte-utilisateur");  
		} else {
			try {
				LOGGER.info("Aucune erreur du compte form, phase ajout utilisateur");  
				userService.addUtilisateur(compteForm.getUtilisateur());
			} catch (FriendlyException e) {
				initModel(model,compteForm);
				bresult.reject(e.getKey());
			}
			redirectAttributes.addFlashAttribute("confirmationCreationCompte", messageSource.getMessage("compte.creation.succes.descriptionContenu",new String[]{compteForm.getUtilisateur().getNom(),compteForm.getUtilisateur().getPrenom()},Locale.getDefault()));
			
			Utilisateur utilisateurPersisted = userService.findByEmail(compteForm.getUtilisateur().getEmail());
			ValidateTechnicalErrorUtils.notNull(utilisateurPersisted, "l'utilisateur inscrit ne doit pas être null");

			userService.autoLogUser(utilisateurPersisted);

			return "redirect:/compte-utilisateur/creation-succes";
		} 
 
	} 
	
	@RequestMapping(value = "/creation-succes", method = RequestMethod.GET)
	public String createUserSucces(Model model){
		LOGGER.info("Affichage page creation compte reussi"); 
		return getBuildedUrlPourCompteUtilisateur("creation-compte-succes");  
	}
	
	@RequestMapping(value = "/access-gestion-compte", method = RequestMethod.GET)
	public String initAccesGestionCompte(Model model) { 
		LOGGER.info("Initialisation de la gestion du compte utilisateur");
		return getBuildedUrlPourCompteUtilisateur("gestion-compte-utilisateur");   
	}
	
	@RequestMapping(value = "/edition-info-generales", method = RequestMethod.GET)
	public String initAccesEditionInformationsGenerales(Model model) { 
		LOGGER.info("Initialisation de l'edition des informations générales"); 
		 
		Utilisateur loggedUser = userService.getCurrentUser(); 
		ValidateTechnicalErrorUtils.notNull(loggedUser, "l'utilisateur connecté ne doit pas être null");
  
		Utilisateur user = userService.getUtilisateurById(loggedUser.getId()); 
		ValidateTechnicalErrorUtils.notNull(user, "l'utilisateur d'id "+loggedUser+" récupéré ne doit pas être null");
	
		model.addAttribute("compteForm",user);
 
		return getBuildedUrlPourCompteUtilisateur("edition-informations-generales");    
	}
	
	@RequestMapping(value = "/edition-info-generales", method = RequestMethod.POST)
	public String editionUser(Model model, @ModelAttribute("compteForm") @Validated({ Default.class }) Utilisateur utilisateur, BindingResult bresult,RedirectAttributes redirectAttributes) { 
		LOGGER.info("Edition du compte utilisateur de creation, compteForm:{}",utilisateur);
	 
		if (bresult.hasErrors()) {
			LOGGER.info("Erreur détecté lors de la validation du compte form"); 
			model.addAttribute("compteForm",utilisateur); 
			return getBuildedUrlPourCompteUtilisateur("edition-informations-generales");     
		}
		
		//rendre plus générique les modif ou se basé sur les champs validés 
		Utilisateur user = userService.getUtilisateurById(utilisateur.getId());  
		ValidateTechnicalErrorUtils.notNull(user, "l'utilisateur d'id "+utilisateur.getId()+" récupéré ne doit pas être null");

		user.setEmail(utilisateur.getEmail());
		user.setNom(utilisateur.getNom());
		user.setPrenom(utilisateur.getPrenom());
		
		LOGGER.info("Mise à jour de l'utilisateur {}",utilisateur); 
		userService.updateUtilisateur(user);
		 
		LOGGER.info("Mise à jour de l'utilisateur effectué",utilisateur); 
		return "redirect:/compte-utilisateur/access-gestion-compte"; 
 
	} 
	
	private void initModel(Model model, UtilisateurForm userForm){
		model.addAttribute("compteForm",userForm);
	}
	
	private String getBuildedUrlPourCompteUtilisateur(String specificPage){
		return "front.compte-utilisateur."+specificPage;
	}
	
}
